package com.duqc.zk.controller;

import com.duqc.zk.ZkLock;
import com.duqc.zk.service.ZkSeckillService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.recipes.locks.InterProcessMutex;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.concurrent.TimeUnit;

/**
 * @ClassName ZkSeckillController
 * @Description TODO
 * @Author duqc
 * @Date 2021/5/13
 **/
@Slf4j
@RestController
@RequestMapping("zk")
@RequiredArgsConstructor
public class ZkSeckillController {

    private final ZkSeckillService zkSeckillService;

    /**
     * 自定义ZooKeeper实现分布式锁
     *
     * @param commodityId
     * @param number
     * @return
     */
    @PostMapping("/purchase")
    public boolean purchaseCommodityInfo(String commodityId, Integer number) {
        boolean bool;
        //获取ZooKeeper分布式锁
        ZkLock zkLock = new ZkLock();
        try {
            //上锁
            zkLock.lock();
            bool = this.zkSeckillService.purchaseCommodityInfo(commodityId, number);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            bool = false;
        } finally {
            zkLock.unlock();
        }
        return bool;
    }

    /**
     * curator插件实现ZooKeeper分布式锁
     *
     * @param commodityId
     * @param number
     * @return
     * @throws Exception
     */
    @PostMapping("/purchase/curator")
    public boolean purchaseCuratorCommodityInfo(String commodityId, Integer number) throws Exception {
        boolean bool = false;
        //设置重试策略
        RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
        CuratorFramework curatorFramework = CuratorFrameworkFactory.newClient("127.0.0.1:2181", retryPolicy);
        //启动客户端
        curatorFramework.start();
        InterProcessMutex mutex = new InterProcessMutex(curatorFramework, "/locks");
        try {
            //加锁
            if (mutex.acquire(3, TimeUnit.SECONDS)) {
                bool = this.zkSeckillService.purchaseCommodityInfo(commodityId, number);
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        } finally {
            //解锁
            mutex.release();
            curatorFramework.close();
        }
        return bool;
    }

}
